package com.qigao.mall.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.qigao.mall.api.*;
import com.qigao.mall.commons.dto.*;
import com.qigao.mall.commons.enums.*;
import com.qigao.mall.commons.exceptions.BusinessException;
import com.qigao.mall.commons.utils.DateUtil;
import com.qigao.mall.commons.utils.IDUtils;
import com.qigao.mall.jdbc.mapper.*;
import com.qigao.mall.jdbc.model.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author luiz
 * @Title: com.qigao.mall.service.impl
 * @ProjectName three-mall
 * @date 2019-11-2019/11/5 13:37
 * @Description:订单服务类
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static Logger logger= LoggerFactory.getLogger(OrderServiceImpl.class);

    @Resource
    DataSourceTransactionManager transactionManager;

    @Resource
    private TbOrderTotalMapper tbOrderTotalMapper;
    @Resource
    private TbOrderDetailMapper tbOrderDetailMapper;
    @Resource
    private TbOrderShippingMapper tbOrderShippingMapper;
    @Resource
    private TbShopCartMapper tbShopCartMapper;
    @Resource
    private TbItemMapper tbItemMapper;
    @Resource
    private TbItemSkuMapper tbItemSkuMapper;
   // @Resource
    //private TbMerInfoMapper tbMerInfoMapper;
    @Resource
    private AccountInfoService accountInfoService;
    @Resource
    private AccountSerivce accountService;
    @Resource
    private TbShopInfoMapper tbShopInfoMapper;
    @Resource
    private ShopEmpService shopEmpService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysCompanyMapper sysCompanyMapper;
    @Resource
    private PromGroupService promGroupService;

    @Value("${qigao.pay.domain}")
    private String payDomain;

    @Override
    public Result createOrder(OrderCreateDto orderCreateDto) {
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setName(TransactionTypeEnum.ORDER_CREATE.getCode());
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try{
            String orderNo= IDUtils.genIdStr(IdTypeEnum.ORDER.getCode());
            TbShopInfo tbShopInfo=tbShopInfoMapper.selectByShopNo(orderCreateDto.getShopNo());
            orderCreateDto.setMerNo(tbShopInfo.getMerNo());
            orderCreateDto.setMerName(tbShopInfo.getMerName());
            orderCreateDto.setShopName(tbShopInfo.getShopName());
            //订单明细表
            List<TbOrderDetail> tbOrderDetails=buildOrderDetailEntity(orderCreateDto,orderNo);
            //送货地址
            TbOrderShipping tbOrderShipping=buildOrderShippingEntity(orderCreateDto,orderNo);
            //订单总表
            TbOrderTotal tbOrderTotal=buildOrderTotalEntity(orderCreateDto,orderNo);
            //是否操作购物车
            if(OrderSourceEnum.SHOP_CART.getCode().equals(orderCreateDto.getOrderSource())){
                List<TbShopCart> itemIndexNos=new ArrayList<>();
                for(OrderCreateDetailDto orderCreateDetailDto:orderCreateDto.getOrderCreateDetailDtoList()){
                    TbShopCart tbShopCart=new TbShopCart();
                    tbShopCart.setItemNo(orderCreateDetailDto.getItemNo());
                    tbShopCart.setUserNo(orderCreateDto.getBuylerId());
                    itemIndexNos.add(tbShopCart);
                }
                tbShopCartMapper.deleteByIndexNos(itemIndexNos);
            }
            //加入团购订单
            if(StringUtils.isNotEmpty(orderCreateDto.getGroupNo())){
                promGroupService.createPromGroupDetail(orderCreateDto.getGroupNo(),tbOrderTotal,tbOrderDetails);
            }
            tbOrderTotalMapper.insertSelective(tbOrderTotal);
            tbOrderDetailMapper.insertBatch(tbOrderDetails);
            tbOrderShippingMapper.insertSelective(tbOrderShipping);
            transactionManager.commit(transactionStatus);
            //积分兑换商品 自动审核通过
            if(OrderTypeEnum.SCORE.getCode().equals(tbOrderTotal.getOrderType())){
                confirmMoney(orderNo,orderCreateDto.getRecvUserNo());
            }
            logger.info("订单创建成功:{}",orderNo);
             return Result.newSuccess(orderNo);
        } catch (BusinessException ge) {
            logger.error("订单创建发生业务异常,事物回滚:{}",  ge);
            transactionManager.rollback(transactionStatus);
            return Result.newError(ge.getCode(), ge.getMsg());
        } catch (Exception e) {
            logger.error("订单创建发生异常,事物回滚:{}",  e);
            transactionManager.rollback(transactionStatus);
            throw new BusinessException(ResultCode.SAVE_DB_ERROR.getCode(), ResultCode.SAVE_DB_ERROR.getMessage());
        }
    }

    @Override
    public Result<PageInfo<OrderResultDto>> findOrderByCond(OrderQueryDto orderQueryDto) {
        PageHelper.startPage(orderQueryDto.getPageNum(),orderQueryDto.getPageSize());
        Page<TbOrderTotal> tbOrderTotalPage=(Page<TbOrderTotal>)tbOrderTotalMapper.selectByCond(orderQueryDto);
        return convertToDto(tbOrderTotalPage);
    }

    @Override
    public List<OrderResultDto> findOrderResultByCond(OrderQueryDto orderQueryDto) {
        List<TbOrderTotal> tbOrderTotals=(List<TbOrderTotal>)tbOrderTotalMapper.selectByCond(orderQueryDto);
        return convertToResultDto(tbOrderTotals);
    }

    private List<OrderResultDto> convertToResultDto(List<TbOrderTotal> tbOrderTotals) {
        List<OrderResultDto> orderResultDtos=new ArrayList<>();
        List<String> orderNos=new ArrayList<>();
        for(TbOrderTotal tbOrderTotal:tbOrderTotals){
            orderNos.add(tbOrderTotal.getOrderNo());
        }
        List<TbOrderDetail> tbOrderDetails=tbOrderDetailMapper.selectByOrderNos(orderNos);
        List<TbOrderShipping> tbOrderShippings=tbOrderShippingMapper.selectByOrderNos(orderNos);
        List<PromGroupResultDto> promGroupResultDtos=promGroupService.selectByOrderNos(orderNos);
        for(TbOrderTotal tbOrderTotal:tbOrderTotals){
            OrderResultDto orderResultDto=buildOrderResult(tbOrderTotal);
            orderResultDto.setOrderDetailResultDtoList(buildOrderDetailResults(tbOrderTotal.getOrderNo(),tbOrderDetails));
            orderResultDto.setOrderShippingResultDto(buildOrderShippingDtos(tbOrderTotal.getOrderNo(),tbOrderShippings)); ;
            orderResultDto.setPromGroupResultDto(buildGroupDto(tbOrderTotal.getOrderNo(),promGroupResultDtos));
            orderResultDtos.add(orderResultDto);
        }
        return orderResultDtos;
    }

    private  List<OrderDetailResultDto> buildOrderDetailResult(TbOrderTotal tbOrderTotal) {
        List<TbOrderDetail> tbOrderDetails=tbOrderDetailMapper.selectByOrderNo(tbOrderTotal.getOrderNo());
        //orderResultDto.setItemNum(String.valueOf(tbOrderDetails.size()));
        //orderResultDto.setPicNo(payDomain+"/common/file/findByNo/"+tbOrderDetails.get(0).getItemNarrowPic());
        List<OrderDetailResultDto> orderDetailResultDtoList=new ArrayList<OrderDetailResultDto>();
        for(TbOrderDetail tbOrderDetail:tbOrderDetails){
            OrderDetailResultDto orderDetailResultDto=new OrderDetailResultDto();
            BeanUtils.copyProperties(tbOrderDetail,orderDetailResultDto);
            orderDetailResultDto.setItemPicUrl(payDomain+"/common/file/findByNo/"+tbOrderDetail.getItemPicUrl());
            orderDetailResultDto.setItemNarrowPic(payDomain+"/common/file/findByNo/"+tbOrderDetail.getItemNarrowPic());
            orderDetailResultDto.setProfitTypeName(ProfitTypeEnum.getNameByCode(tbOrderDetail.getProfitType()));
            orderDetailResultDtoList.add(orderDetailResultDto);
        }
        return orderDetailResultDtoList;
    }

    @Override
    public Result<PageInfo<OrderResultDto>> findOrderByRecvUserNo(OrderQueryDto orderQueryDto) {
        PageHelper.startPage(orderQueryDto.getPageNum(),orderQueryDto.getPageSize());
        Page<TbOrderTotal> tbOrderTotalPage=(Page<TbOrderTotal>)tbOrderTotalMapper.selectByRecvUserNo(orderQueryDto);
        return convertToDto(tbOrderTotalPage);
    }

    @Override
    public Result<PageInfo<OrderResultDto>> findOrderByInviteUserNo(OrderQueryDto orderQueryDto) {
        PageHelper.startPage(orderQueryDto.getPageNum(),orderQueryDto.getPageSize());
        Page<TbOrderTotal> tbOrderTotalPage=(Page<TbOrderTotal>)tbOrderTotalMapper.selectByInviteUserNo(orderQueryDto);
        return convertToDto(tbOrderTotalPage);
    }

    private OrderResultDto buildOrderResult(TbOrderTotal tbOrderTotal) {
        OrderResultDto orderResultDto=new OrderResultDto();
        BeanUtils.copyProperties(tbOrderTotal,orderResultDto);
        orderResultDto.setOrderDate(DateUtil.getDateTimeFormat(tbOrderTotal.getOrderTime()));
        orderResultDto.setActOrderAmt(tbOrderTotal.getActOrderAmt().toString());
        orderResultDto.setOrderStatus(tbOrderTotal.getOrderStatus().toString());
        orderResultDto.setOrderStatusName(OrderStatusEnum.getNameByCode(tbOrderTotal.getOrderStatus()));
        orderResultDto.setOrderTime(DateUtil.getDateTimeFormat(tbOrderTotal.getOrderTime()));
        orderResultDto.setPayTime(DateUtil.getDateTimeFormat(tbOrderTotal.getPayTime()));
        orderResultDto.setOverTime(DateUtil.getDateTimeFormat(tbOrderTotal.getOverTime()));
        orderResultDto.setCancelTime(DateUtil.getDateTimeFormat(tbOrderTotal.getCancelTime()));
        orderResultDto.setAutoFinishTime(DateUtil.getDateTimeFormat(tbOrderTotal.getAutoFinishTime()));
        orderResultDto.setConfirmMoneyTime(DateUtil.getDateTimeFormat(tbOrderTotal.getConfirmMoneyTime()));
        orderResultDto.setSendGoodsTime(DateUtil.getDateTimeFormat(tbOrderTotal.getSendGoodsTime()));
        orderResultDto.setConfirmGoodsTime(DateUtil.getDateTimeFormat(tbOrderTotal.getConfirmGoodsTime()));
        orderResultDto.setOrderTypeName(OrderTypeEnum.getNameByCode(tbOrderTotal.getOrderType()));
        return orderResultDto;
    }

    @Override
    public  Result<OrderResultDto> findOrderByNo(String orderNo) {
       TbOrderTotal tbOrderTotal=tbOrderTotalMapper.selectByOrderNo(orderNo);
       if(tbOrderTotal==null){
           return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
       }
        OrderResultDto orderResultDto=buildOrderResultDto(tbOrderTotal);
        return Result.newSuccess(orderResultDto);
    }

    private OrderResultDto buildOrderResultDto(TbOrderTotal tbOrderTotal) {
        OrderResultDto orderResultDto=buildOrderResult(tbOrderTotal);
        List<TbOrderDetail> tbOrderDetails=tbOrderDetailMapper.selectByOrderNo(tbOrderTotal.getOrderNo());
        List<OrderDetailResultDto> orderDetailResultDtos=new ArrayList<>();
        for(TbOrderDetail tbOrderDetail:tbOrderDetails){
            OrderDetailResultDto orderDetailResultDto=new OrderDetailResultDto();
            BeanUtils.copyProperties(tbOrderDetail,orderDetailResultDto);
            orderDetailResultDto.setProfitTypeName(ProfitTypeEnum.getNameByCode(orderDetailResultDto.getProfitType()));
            orderDetailResultDto.setItemPicUrl(payDomain+"/common/file/findByNo/"+tbOrderDetail.getItemPicUrl());
            orderDetailResultDtos.add(orderDetailResultDto);
        }
        orderResultDto.setOrderDetailResultDtoList(orderDetailResultDtos);
        orderResultDto.setItemNum(String.valueOf(tbOrderDetails.size()));
        orderResultDto.setPicNo(tbOrderDetails.get(0).getItemPicUrl());
        orderResultDto.setOrderShippingResultDto(buildOrderShippingDto(tbOrderTotal.getOrderNo()));
        orderResultDto.setPromGroupResultDto(buildGroupResultDto(tbOrderTotal.getOrderNo()));
        return orderResultDto;
    }

    private PromGroupResultDto buildGroupResultDto(String orderNo) {
       return  promGroupService.selectByOrderNo(orderNo);
    }

    @Override
    public Result<OrderResultDto> findOrderByRecv(String orderRecv, String userNo) {
        TbOrderTotal tbOrderTotal=tbOrderTotalMapper.selectByOrderRecv(orderRecv,userNo);
        if(tbOrderTotal==null){
            return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
        }
        OrderResultDto orderResultDto=buildOrderResultDto(tbOrderTotal);
        return Result.newSuccess(orderResultDto);
    }

    @Override
    public Result<OrderResultDto> findShopOrderByRecv(String orderRecv, String shopNo) {
        TbOrderTotal tbOrderTotal=tbOrderTotalMapper.selectShopOrderByOrderRecv(orderRecv,shopNo);
        if(tbOrderTotal==null){
            return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
        }
        OrderResultDto orderResultDto=buildOrderResultDto(tbOrderTotal);
        return Result.newSuccess(orderResultDto);
    }

    private Result<PageInfo<OrderResultDto>> convertToDto(Page<TbOrderTotal> tbOrderTotalPage) {
        if(tbOrderTotalPage.getResult()==null || tbOrderTotalPage.getResult().size()==0){
            return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
        }
        Page<OrderResultDto> orderResultDtoPage=new Page<>();
        BeanUtils.copyProperties(tbOrderTotalPage,orderResultDtoPage);
        List<TbOrderTotal> tbOrderTotals=tbOrderTotalPage.getResult();
        List<String> orderNos=new ArrayList<>();
        for(TbOrderTotal tbOrderTotal:tbOrderTotals){
            orderNos.add(tbOrderTotal.getOrderNo());
        }
        List<TbOrderDetail> tbOrderDetails=tbOrderDetailMapper.selectByOrderNos(orderNos);
        List<TbOrderShipping> tbOrderShippings=tbOrderShippingMapper.selectByOrderNos(orderNos);
        List<PromGroupResultDto> promGroupResultDtos=promGroupService.selectByOrderNos(orderNos);
        for(TbOrderTotal tbOrderTotal:tbOrderTotals){
            OrderResultDto orderResultDto=buildOrderResult(tbOrderTotal);
            orderResultDto.setOrderDetailResultDtoList(buildOrderDetailResults(tbOrderTotal.getOrderNo(),tbOrderDetails));
            orderResultDto.setOrderShippingResultDto(buildOrderShippingDtos(tbOrderTotal.getOrderNo(),tbOrderShippings)); ;
            orderResultDto.setPromGroupResultDto(buildGroupDto(tbOrderTotal.getOrderNo(),promGroupResultDtos));
            orderResultDtoPage.add(orderResultDto);
        }
        return Result.newSuccess(new PageInfo<>(orderResultDtoPage));
    }

    private PromGroupResultDto buildGroupDto(String orderNo, List<PromGroupResultDto> promGroupResultDtos) {
        for(PromGroupResultDto promGroupResultDto:promGroupResultDtos){
            for(PromGroupDetailResultDto promGroupDetailResultDto:promGroupResultDto.getPromGroupDetailResultDtoList()){
                if(orderNo.equals(promGroupDetailResultDto.getOrderNo())){
                    return promGroupResultDto;
                }
            }
        }
        return null;
    }

    private List<OrderDetailResultDto> buildOrderDetailResults(String orderNo,List<TbOrderDetail> tbOrderDetails) {
        List<OrderDetailResultDto> orderDetailResultDtoList=new ArrayList<OrderDetailResultDto>();
        for(TbOrderDetail tbOrderDetail:tbOrderDetails){
            if(tbOrderDetail.getOrderNo().equals(orderNo)){
                OrderDetailResultDto orderDetailResultDto=new OrderDetailResultDto();
                BeanUtils.copyProperties(tbOrderDetail,orderDetailResultDto);
                orderDetailResultDto.setItemPicUrl(payDomain+"/common/file/findByNo/"+tbOrderDetail.getItemPicUrl());
                orderDetailResultDto.setItemNarrowPic(payDomain+"/common/file/findByNo/"+tbOrderDetail.getItemNarrowPic());
                orderDetailResultDto.setProfitTypeName(ProfitTypeEnum.getNameByCode(tbOrderDetail.getProfitType()));
                orderDetailResultDtoList.add(orderDetailResultDto);
            }
        }
        return orderDetailResultDtoList;
    }

    private OrderShippingResultDto buildOrderShippingDtos(String orderNo,List<TbOrderShipping> tbOrderShippings) {
        OrderShippingResultDto orderShippingResultDto=new OrderShippingResultDto();
        TbOrderShipping tbOrderShipping=tbOrderShippings.stream().filter(o->o.getOrderNo().equals(orderNo)).findFirst().orElse(null);
        return  convertShippingToDto(tbOrderShipping);
    }
    private OrderShippingResultDto buildOrderShippingDto(String orderNo) {
        TbOrderShipping tbOrderShipping=tbOrderShippingMapper.selectByOrderNo(orderNo);
        return  convertShippingToDto(tbOrderShipping);
    }

    private OrderShippingResultDto convertShippingToDto(TbOrderShipping tbOrderShipping) {
        if(tbOrderShipping!=null){
            OrderShippingResultDto orderShippingResultDto=new OrderShippingResultDto();
            BeanUtils.copyProperties(tbOrderShipping,orderShippingResultDto);
            SysUser inviteUser=sysUserMapper.selectInviteUserByNo(orderShippingResultDto.getRecvUserNo());
            if(inviteUser!=null){
                orderShippingResultDto.setRecvInviteUserNo(inviteUser.getUserNo());
                orderShippingResultDto.setRecvInviteUserName(inviteUser.getUserName());
            }
            if(StringUtils.isNotEmpty(tbOrderShipping.getProvinceCode())){
                int lastIndex=tbOrderShipping.getProvinceCode().indexOf("-");
                orderShippingResultDto.setRecvProvinceCode(tbOrderShipping.getProvinceCode());
                if(lastIndex!=-1)
                    orderShippingResultDto.setRecvProvinceCode(tbOrderShipping.getProvinceCode().substring(0,lastIndex));
            }
            if(StringUtils.isNotEmpty(tbOrderShipping.getCityCode())){
                int lastIndex=tbOrderShipping.getCityCode().lastIndexOf("-");
                orderShippingResultDto.setRecvCityCode(tbOrderShipping.getCityCode());
                if(lastIndex!=-1)
                    orderShippingResultDto.setRecvCityCode(tbOrderShipping.getCityCode().substring(0,lastIndex));
            }
            if(StringUtils.isNotEmpty(tbOrderShipping.getDistrictCode())){
                int lastIndex=tbOrderShipping.getDistrictCode().lastIndexOf("-");
                orderShippingResultDto.setRecvDistrictCode(tbOrderShipping.getDistrictCode());
                if(lastIndex!=-1)
                    orderShippingResultDto.setRecvDistrictCode(tbOrderShipping.getDistrictCode().substring(0,lastIndex));
            }
            return orderShippingResultDto;
        }
        return null;
    }

    @Override
    public Result updateOrder(OrderModiDto orderModiDto) {
        TbOrderTotal tbOrderTotal=new TbOrderTotal();
        BeanUtils.copyProperties(orderModiDto,tbOrderTotal);
        tbOrderTotal.setModiNo(orderModiDto.getUserNo());
        tbOrderTotal.setModiTime(new Date());
        tbOrderTotalMapper.updateByOrderNo(tbOrderTotal);
        TbOrderShipping tbOrderShipping=new TbOrderShipping();
        tbOrderShipping.setOrderNo(orderModiDto.getOrderNo());
        tbOrderShipping.setRecvName(orderModiDto.getRecvName());
        tbOrderShipping.setRecvAddress(orderModiDto.getRecvAddress());
        tbOrderShipping.setRecvCity(orderModiDto.getRecvCity());
        tbOrderShipping.setRecvDistrict(orderModiDto.getRecvDistrict());
        tbOrderShipping.setRecvProvince(orderModiDto.getRecvProvince());
        tbOrderShipping.setRecvPhone(orderModiDto.getRecvPhone());
        tbOrderShipping.setRecvZip(orderModiDto.getRecvZip());
        tbOrderShipping.setShippingNo(orderModiDto.getShippingNo());
        tbOrderShipping.setShippingWay(orderModiDto.getShippingWay());
        tbOrderShipping.setModiNo(orderModiDto.getUserNo());
        tbOrderShipping.setModiTime(new Date());
        tbOrderShippingMapper.updateByOrderNo(tbOrderShipping);
        return Result.newSuccess();
    }

    @Override
    public Result<PageInfo<OrderResultDto>> findAllPayOrderList(OrderQueryDto orderQueryDto) {
        PageHelper.startPage(orderQueryDto.getPageNum(),orderQueryDto.getPageSize());
        Page<TbOrderTotal> tbOrderTotalPage=(Page<TbOrderTotal>)tbOrderTotalMapper.selectPayOrderList(orderQueryDto);
        if(tbOrderTotalPage.getResult()==null || tbOrderTotalPage.getResult().size()==0){
            return Result.newError(ResultCode.COMMON_DATA_NOT_EXISTS);
        }
        Page<OrderResultDto> orderResultDtoPage=new Page<>();
        BeanUtils.copyProperties(tbOrderTotalPage,orderResultDtoPage);
        for(TbOrderTotal tbOrderTotal:tbOrderTotalPage.getResult()){
            OrderResultDto orderResultDto=buildOrderResult(tbOrderTotal);
            List<TbOrderDetail> tbOrderDetails=tbOrderDetailMapper.selectByOrderNo(tbOrderTotal.getOrderNo());
            orderResultDto.setItemNum(String.valueOf(tbOrderDetails.size()));
            orderResultDto.setPicNo(tbOrderDetails.get(0).getItemPicUrl());
            orderResultDtoPage.add(orderResultDto);
        }
        return Result.newSuccess(new PageInfo<>(orderResultDtoPage));
    }


    @Override
    public void refreshOrderOverTime() {
        List<TbOrderTotal> tbOrderTotals=tbOrderTotalMapper.selectOrderWhenOverTime();
        for(TbOrderTotal tbOrderTotal : tbOrderTotals){
            TbOrderTotal tbOrderTotal1=new TbOrderTotal();
            tbOrderTotal1.setOrderNo(tbOrderTotal.getOrderNo());
            tbOrderTotal1.setOrderStatus(OrderStatusEnum.CLOSE.getCode());
            tbOrderTotal1.setVersion(tbOrderTotal.getVersion());
            tbOrderTotalMapper.updateOrderStatus(tbOrderTotal1);
        }
    }

    @Override
    public void autoRecvOrder() {
        List<TbOrderTotal> tbOrderTotals=tbOrderTotalMapper.selectOrderWhenOverRecv();
        for(TbOrderTotal tbOrderTotal : tbOrderTotals){
            TbOrderTotal tbOrderTotal1=new TbOrderTotal();
            tbOrderTotal1.setOrderNo(tbOrderTotal.getOrderNo());
            tbOrderTotal1.setOrderStatus(OrderStatusEnum.HAS_RECV.getCode());
            tbOrderTotal1.setVersion(tbOrderTotal.getVersion());
            tbOrderTotal1.setAutoFinishTime(new Date());
            tbOrderTotalMapper.updateOrderStatus(tbOrderTotal1);
        }
    }

    @Override
    public Result<SaleMonthReportDto> findSaleReport(MonthReportDto monthReportDto) {
        SaleMonthReportDto saleMonthReportDto=tbOrderTotalMapper.sumOrderMonthReport(monthReportDto);
        if(saleMonthReportDto==null){
            saleMonthReportDto=new SaleMonthReportDto();
            saleMonthReportDto.setSaleMonth(monthReportDto.getMonthNum());
        }
        SaleMonthReportDto orderReportDto=tbOrderTotalMapper.sumYesterdayOrder(monthReportDto);
        SaleMonthReportDto payReportDto=tbOrderTotalMapper.sumYesterdayPay(monthReportDto);
        if(orderReportDto!=null){
            saleMonthReportDto.setYesterdayOrderNum(orderReportDto.getYesterdayOrderNum());
        }
        if(payReportDto!=null){
            saleMonthReportDto.setYesterdayPayAmt(payReportDto.getYesterdayPayAmt());
            saleMonthReportDto.setYesterdayPayNum(payReportDto.getYesterdayPayNum());
        }
        if(saleMonthReportDto.getYesterdayOrderNum().compareTo(BigDecimal.ZERO)==1){
            BigDecimal payRate=saleMonthReportDto.getYesterdayPayNum().divide(saleMonthReportDto.getYesterdayOrderNum());
             payRate=payRate.multiply(new BigDecimal(100));
            saleMonthReportDto.setYesterdayPayRate(payRate.setScale(2));
        }
        return Result.newSuccess(saleMonthReportDto);
    }

    /**
     * 确认收钱
     * @param orderNo
     * @param userNo
     * @return
     */
    private Result confirmMoney(String orderNo,String userNo){
        OrderModiDto orderModiDto=new OrderModiDto();
        orderModiDto.setOrderAction(OrderActionEnum.CONFIRM_MONEY);
        orderModiDto.setOrderNo(orderNo);
        orderModiDto.setUserNo(userNo);
        orderModiDto.setOrderStatus(OrderStatusEnum.HAS_PAY.getCode());
       return updateOrderStatus(orderModiDto);
    }



    @Override
    public Result updateOrderStatus(OrderModiDto orderModiDto) {
        //状态机检查
        TbOrderTotal tbOrderTotal=tbOrderTotalMapper.selectByOrderNo(orderModiDto.getOrderNo());
        boolean flag=checkOrderStatus(tbOrderTotal.getOrderNo(),tbOrderTotal.getOrderStatus(),orderModiDto.getOrderStatus());
        if(!flag){
            return Result.newError(ResultCode.OPER_NOT_ALlOWED);
        }
        //更新状态
        tbOrderTotal.setOrderStatus(Integer.valueOf(orderModiDto.getOrderStatus()));
        if(OrderActionEnum.CONFIRM_MONEY.equals(orderModiDto.getOrderAction())){//商家确认收钱
            tbOrderTotal.setConfirmMoneyTime(new Date());
            //添加积分
            addScoreAccount(tbOrderTotal);
        }else if(OrderActionEnum.CONFIRM_SEND.equals(orderModiDto.getOrderAction())){//商家确认发货
            tbOrderTotal.setSendGoodsTime(new Date());
        }else if(OrderActionEnum.CONFIRM_RECV.equals(orderModiDto.getOrderAction())){//客户确认收货
            tbOrderTotal.setConfirmGoodsTime(new Date());
        }else if(OrderActionEnum.ORDER_CANCEL.equals(orderModiDto.getOrderAction())){//客户取消订单
            tbOrderTotal.setCancelTime(new Date());
        }else if(OrderActionEnum.ORDER_DELETE.equals(orderModiDto.getOrderAction())){//客户删除订单
        }
        tbOrderTotal.setModiNo(orderModiDto.getUserNo());
        tbOrderTotal.setModiTime(new Date());
        int updateNum=tbOrderTotalMapper.updateOrderStatus(tbOrderTotal);
        if(updateNum!=1){
            return Result.newError(ResultCode.DB_VERSION_UPDATE_ERROR);
        }
        TbOrderShipping tbOrderShipping=new TbOrderShipping();
        tbOrderShipping.setOrderNo(orderModiDto.getOrderNo());
        tbOrderShipping.setRecvName(orderModiDto.getRecvName());
        tbOrderShipping.setRecvAddress(orderModiDto.getRecvAddress());
        tbOrderShipping.setRecvCity(orderModiDto.getRecvCity());
        tbOrderShipping.setRecvDistrict(orderModiDto.getRecvDistrict());
        tbOrderShipping.setRecvProvince(orderModiDto.getRecvProvince());
        tbOrderShipping.setRecvPhone(orderModiDto.getRecvPhone());
        tbOrderShipping.setRecvZip(orderModiDto.getRecvZip());
        tbOrderShipping.setShippingNo(orderModiDto.getShippingNo());
        tbOrderShipping.setShippingWay(orderModiDto.getShippingWay());
        tbOrderShipping.setModiNo(orderModiDto.getUserNo());
        tbOrderShipping.setModiTime(new Date());
        tbOrderShippingMapper.updateByOrderNo(tbOrderShipping);
        return Result.newSuccess();
    }


    /**
     * 给账户添加积分
     * @param tbOrderTotal
     */
    private void addScoreAccount(TbOrderTotal tbOrderTotal) {
        TbOrderShipping tbOrderShipping=tbOrderShippingMapper.selectByOrderNo(tbOrderTotal.getOrderNo());
        TbAccountInfo tbAccountInfo=accountInfoService.saveUserAccount(tbOrderShipping.getRecvUserNo(),AccountTypeEnum.SCORE_ACCOUNT);
        AccountAmtOperDto accountAmtOperDto=new AccountAmtOperDto();
        accountAmtOperDto.setAccoutNo(tbAccountInfo.getAccountNo());
        accountAmtOperDto.setSourceOrderNo(tbOrderTotal.getOrderNo());
        accountAmtOperDto.setSourceTradeType(TradeTypeEnum.ACQUIRE_SCORE);
        accountAmtOperDto.setTradeAmt(tbOrderTotal.getCustomerScore());
        accountService.operAccountAmt(accountAmtOperDto);
    }



    @Override
    public Result updateOrderStatusBatch(List<OrderModiDto> orderModiDtos) {
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setName(TransactionTypeEnum.ORDER_MODI.getCode());
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try{
            for(OrderModiDto orderModiDto:orderModiDtos){
                Result updateResult = updateOrderStatus(orderModiDto);
                if(!updateResult.isSuccess()){
                    throw new BusinessException(updateResult.getRetCode(),updateResult.getRetMsg());
                }
            }
            transactionManager.commit(transactionStatus);
            logger.info("批量修改订单状态成功");
            return Result.newSuccess();
        } catch (BusinessException ge) {
            logger.error("批量修改订单发生业务异常,事物回滚:{}",  ge);
            transactionManager.rollback(transactionStatus);
            return Result.newError(ge.getCode(), ge.getMsg());
        } catch (Exception e) {
            logger.error("批量修改订单发生异常,事物回滚:{}",  e);
            transactionManager.rollback(transactionStatus);
            throw new BusinessException(ResultCode.SAVE_DB_ERROR.getCode(), ResultCode.SAVE_DB_ERROR.getMessage());
        }

    }




    /**
     * 状态变更检查
     * @param orderNo
     * @param sourceOrderStatus
     * @param destOrderStatus
     * @return
     */
    private boolean checkOrderStatus(String orderNo,int sourceOrderStatus, int destOrderStatus) {
        if(destOrderStatus==OrderStatusEnum.HAS_PAY.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.INIT.getCode())){
                return true;
            }
        }
        if(destOrderStatus==OrderStatusEnum.HAS_SEND.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.HAS_PAY.getCode())){
                return true;
            }
        }
        if(destOrderStatus==OrderStatusEnum.HAS_RECV.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.HAS_SEND.getCode())){
                return true;
            }
        }
        if(destOrderStatus==OrderStatusEnum.REFUND_PROC.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.HAS_RECV.getCode())){
                return true;
            }
        }
        if(destOrderStatus==OrderStatusEnum.CLOSE.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.INIT.getCode())){
                return true;
            }
        }
        if(destOrderStatus==OrderStatusEnum.DELETED.getCode()){
            if(!ObjectUtils.notEqual(sourceOrderStatus,OrderStatusEnum.HAS_PAY.getCode())){
                return true;
            }
        }
        logger.warn("订单号：{}不能从{}变为{}",orderNo,sourceOrderStatus,destOrderStatus);
        return false;
    }

    @Override
    public Result updateMerOrder(OrderModiDto orderModiDto) {
        boolean ifExistsShopEmp=shopEmpService.ifShopEmp(orderModiDto.getShopNo(),orderModiDto.getUserNo());
        if(!ifExistsShopEmp){
            logger.error("非本店铺店员，不能操作订单{}",orderModiDto);
            throw new BusinessException(ResultCode.OPER_NOT_ALlOWED);
        }
        TbOrderTotal tbOrderTotal=new TbOrderTotal();
        tbOrderTotal.setOrderNo(orderModiDto.getOrderNo());
        tbOrderTotal.setActOrderAmt(orderModiDto.getActOrderAmt());
        tbOrderTotal.setMerMemo(orderModiDto.getMerMemo());
        tbOrderTotal.setModiNo(orderModiDto.getUserNo());
        tbOrderTotal.setModiTime(new Date());
        tbOrderTotalMapper.updateByOrderNo(tbOrderTotal);
        return Result.newSuccess();
    }



    private TbOrderShipping buildOrderShippingEntity(OrderCreateDto orderCreateDto,String orderNo) {
        TbOrderShipping tbOrderShipping=new TbOrderShipping();
        tbOrderShipping.setOrderNo(orderNo);
        tbOrderShipping.setShippingWay(orderCreateDto.getShippingWay());
        tbOrderShipping.setShippingNo(orderCreateDto.getShippingNo());
        tbOrderShipping.setProvinceCode(orderCreateDto.getProvinceCode());
        tbOrderShipping.setRecvProvince(orderCreateDto.getRecvProvince());
        tbOrderShipping.setCityCode(orderCreateDto.getCityCode());
        tbOrderShipping.setRecvCity(orderCreateDto.getRecvCity());
        tbOrderShipping.setDistrictCode(orderCreateDto.getDistrictCode());
        tbOrderShipping.setRecvDistrict(orderCreateDto.getRecvDistrict());
        tbOrderShipping.setRecvAddress(orderCreateDto.getRecvAddress());
        tbOrderShipping.setRecvUserNo(orderCreateDto.getRecvUserNo());
        tbOrderShipping.setRecvName(orderCreateDto.getRecvName());
        tbOrderShipping.setRecvPhone(orderCreateDto.getRecvPhone());
        tbOrderShipping.setRecvZip(orderCreateDto.getRecvZip());
        //SysUser sysUser=sysUserMapper.selectByUserNo(tbOrderShipping.getRecvUserNo());
       // tbOrderShipping.setCompNo(sysUser.getCompNo());
       // SysCompany sysCompany=sysCompanyMapper.selectByCompNo(sysUser.getCompNo());
        //if(sysCompany!=null)
         //   tbOrderShipping.setCompName(sysCompany.getCompName());
        tbOrderShipping.setStatus(YesNoEnum.YES.getCode());
        tbOrderShipping.setCreateTime(new Date());
        tbOrderShipping.setCreateNo(orderCreateDto.getBuylerId());
        tbOrderShipping.setModiNo(orderCreateDto.getBuylerId());
        tbOrderShipping.setCreateTime(new Date());
        tbOrderShipping.setModiTime(new Date());
        return tbOrderShipping;
    }

    private  List<TbOrderDetail>  buildOrderDetailEntity(OrderCreateDto orderCreateDto, String orderNo) {
        List<TbOrderDetail> tbOrderDetails= Lists.newArrayList();
        BigDecimal orderAmt=BigDecimal.ZERO;
        BigDecimal costOrderAmt=BigDecimal.ZERO;
        BigDecimal totalCoupAmt=BigDecimal.ZERO;
        BigDecimal totalScoreAmt=BigDecimal.ZERO;
        BigDecimal totalCustomerScoreAmt=BigDecimal.ZERO;
        for(OrderCreateDetailDto orderCreateDetailDto:orderCreateDto.getOrderCreateDetailDtoList()){
            TbOrderDetail tbOrderDetail=new TbOrderDetail();
            tbOrderDetail.setOrderNo(orderNo);
            tbOrderDetail.setItemNo(orderCreateDetailDto.getItemNo());

            TbItem tbItem=tbItemMapper.selectByItemNo(orderCreateDetailDto.getItemNo());
            if(tbItem==null){
                logger.warn("商品:{}不存在",orderCreateDetailDto.getItemNo());
                throw new BusinessException(ResultCode.OPER_NOT_ALlOWED.getCode(),"商品已下架或者不存在,请联系店主!");
            }
            tbOrderDetail.setItemName(tbItem.getItemTitle());

            TbItemSku tbItemSku=tbItemSkuMapper.selectByStockNo(orderCreateDetailDto.getStockNo());
            BigDecimal itemPrice=BigDecimal.ZERO;
            BigDecimal costPrice=BigDecimal.ZERO;
            BigDecimal scorePercnet=BigDecimal.ZERO;
            if(tbItemSku==null){
                logger.warn("库存编号:{}不存在",orderCreateDetailDto.getStockNo());
                tbOrderDetail.setItemPicUrl(tbItem.getPicUrl());
                tbOrderDetail.setItemNarrowPic(tbItem.getNarrowPicUrl());
                tbOrderDetail.setPrice(tbItem.getPrice());
                itemPrice=tbItem.getPrice();
                costPrice=tbItem.getCost();
            }else{
                tbOrderDetail.setStockNo(orderCreateDetailDto.getStockNo());
                tbOrderDetail.setStockName(tbItemSku.getStockTitle());
                tbOrderDetail.setItemPicUrl(tbItemSku.getPicUrl());
                tbOrderDetail.setItemNarrowPic(tbItemSku.getNarrowPicUrl());
                tbOrderDetail.setPrice(tbItemSku.getPrice());
                tbOrderDetail.setProfitType(tbItemSku.getProfitType());
                itemPrice=tbItemSku.getPrice();
                costPrice=tbItemSku.getCost();
                if(tbItemSku.getScorePercent()!=null)
                scorePercnet=tbItemSku.getScorePercent();
            }
            BigDecimal buyNum=new BigDecimal(orderCreateDetailDto.getBuyNum());
            BigDecimal itemAmt=itemPrice.multiply(buyNum);
            tbOrderDetail.setNum(buyNum);
            tbOrderDetail.setAmt(itemAmt);
            //如果是积分兑换商品，需要考虑积分账户余额是否充足 todo 下单直接扣积分
            if(ProfitTypeEnum.SCORE.getCode().equals(tbItemSku.getProfitType())){
                TbAccountInfo tbAccountInfo=accountInfoService.saveUserAccount(orderCreateDto.getRecvUserNo(),AccountTypeEnum.SCORE_ACCOUNT);
                if(tbAccountInfo.getAccountAmt().compareTo(itemAmt)<=0){
                    logger.warn("账户:{}积分不足",orderCreateDto.getRecvUserNo());
                    throw new BusinessException(ResultCode.ACCOUNT_SCORE_NOT_ENOUGH);
                }
                AccountAmtOperDto accountAmtOperDto=new AccountAmtOperDto();
                accountAmtOperDto.setAccoutNo(tbAccountInfo.getAccountNo());
                accountAmtOperDto.setSourceOrderNo(orderNo);
                accountAmtOperDto.setSourceTradeType(TradeTypeEnum.CONSUMER_SCORE);
                accountAmtOperDto.setTradeAmt(BigDecimal.ZERO.subtract(itemAmt));
                boolean subScoreFlag=accountService.operAccountAmt(accountAmtOperDto);
                if(!subScoreFlag){
                    logger.warn("账户:{}积分不足",orderCreateDto.getRecvUserNo());
                    throw new BusinessException(ResultCode.ACCOUNT_SCORE_NOT_ENOUGH);
                }
            }
            BigDecimal coupAmt=orderCreateDetailDto.getCoupAmt();
            BigDecimal scoreAmt=orderCreateDetailDto.getScoreAmt();
            tbOrderDetail.setCoupAmt(coupAmt);
            tbOrderDetail.setScoreAmt(scoreAmt);
            BigDecimal actOrderAmt=itemAmt.subtract(coupAmt).subtract(scoreAmt);
            tbOrderDetail.setActOrderAmt(actOrderAmt);
            BigDecimal costAmt=costPrice.multiply(buyNum);
            tbOrderDetail.setCostPrice(costPrice);
            tbOrderDetail.setCostAmt(costAmt);
            tbOrderDetail.setVersion(1);
            tbOrderDetail.setCreateNo(orderCreateDto.getBuylerId());
            tbOrderDetail.setModiNo(orderCreateDto.getBuylerId());
            tbOrderDetail.setCreateTime(new Date());
            tbOrderDetail.setModiTime(new Date());
            //获得积分根据商品配置动态计算出来
            BigDecimal customerScoreAmt=itemAmt.multiply(scorePercnet).divide(new BigDecimal(100)).setScale(2,BigDecimal.ROUND_HALF_UP);
            tbOrderDetail.setCustomerScore(customerScoreAmt);
            tbOrderDetails.add(tbOrderDetail);
            orderAmt=orderAmt.add(itemAmt);
            costOrderAmt=costOrderAmt.add(costAmt);
            totalCoupAmt=totalCoupAmt.add(orderCreateDetailDto.getCoupAmt());
            totalScoreAmt=totalScoreAmt.add(orderCreateDetailDto.getScoreAmt());
            totalCustomerScoreAmt=totalCustomerScoreAmt.add(customerScoreAmt);
        }
        orderCreateDto.setOrderAmt(orderAmt);
        orderCreateDto.setCostAmt(costOrderAmt);
        orderCreateDto.setCoupAmt(totalCoupAmt);
        orderCreateDto.setScoreAmt(totalScoreAmt);
        orderCreateDto.setCustomerScore(totalCustomerScoreAmt);
        return tbOrderDetails;
    }

    private TbOrderTotal buildOrderTotalEntity(OrderCreateDto orderCreateDto,String orderNo) {
        TbOrderTotal tbOrderTotal=new TbOrderTotal();
        tbOrderTotal.setOrderNo(orderNo);
        String orderRecv= RandomStringUtils.randomAlphanumeric(8).toUpperCase();
        tbOrderTotal.setOrderRecv(orderRecv);//取单短码
        tbOrderTotal.setOrderType(orderCreateDto.getOrderType());
        tbOrderTotal.setPayType(Integer.valueOf(orderCreateDto.getPayType()));
        tbOrderTotal.setRecvType(Integer.valueOf(orderCreateDto.getRecvType()));
        tbOrderTotal.setOrderTime(new Date());
        BigDecimal orderAmt=orderCreateDto.getOrderAmt();
        BigDecimal coupAmt=orderCreateDto.getCoupAmt();
        String shippingAmtStr= StringUtils.isEmpty(orderCreateDto.getShippingAmt()) ?"0.00":orderCreateDto.getShippingAmt();
        BigDecimal shippingAmt=new BigDecimal(shippingAmtStr);
        tbOrderTotal.setOrderAmt(orderAmt);
        tbOrderTotal.setCoupAmt(coupAmt);
        BigDecimal scoreAmt=orderCreateDto.getScoreAmt();
        tbOrderTotal.setScoreAmt(orderCreateDto.getScoreAmt());//抵扣积分
        tbOrderTotal.setCustomerScore(orderCreateDto.getCustomerScore());//获取积分
        tbOrderTotal.setTransAmt(shippingAmt);
        //应收金额
        BigDecimal recvOrderAmt=orderAmt.add(shippingAmt).subtract(coupAmt).subtract(scoreAmt);
        tbOrderTotal.setRecvOrderAmt(recvOrderAmt);
        //实收金额
        tbOrderTotal.setActOrderAmt(recvOrderAmt);
        tbOrderTotal.setCustomerScore(orderCreateDto.getCustomerScore());
        tbOrderTotal.setCostAmt(orderCreateDto.getCostAmt());
        tbOrderTotal.setOrderDesc("商品来自"+orderCreateDto.getShopName());
        tbOrderTotal.setBuylerId(orderCreateDto.getBuylerId());
        tbOrderTotal.setBuylerName(orderCreateDto.getBuylerName());
        SysUser sysUser=sysUserMapper.selectByUserNo(orderCreateDto.getBuylerId());
        tbOrderTotal.setCompNo(sysUser.getCompNo());
        SysCompany sysCompany=sysCompanyMapper.selectByCompNo(sysUser.getCompNo());
        if(sysCompany!=null)
        tbOrderTotal.setCompName(sysCompany.getCompName());
        tbOrderTotal.setUserMemo(orderCreateDto.getBuylerMemo());//买家备注
        tbOrderTotal.setShopNo(orderCreateDto.getShopNo());
        tbOrderTotal.setMerNo(orderCreateDto.getMerNo());
        tbOrderTotal.setMerName(orderCreateDto.getMerName());
        tbOrderTotal.setOverTime(DateUtil.addDay(new Date(),5));// 过期时间
        tbOrderTotal.setVersion(1);
        tbOrderTotal.setCreateNo(orderCreateDto.getBuylerId());
        tbOrderTotal.setModiNo(orderCreateDto.getBuylerId());
        tbOrderTotal.setCreateTime(new Date());
        tbOrderTotal.setModiTime(new Date());
        return tbOrderTotal;
    }
}
